using System;
using System.Collections.Generic;
using System.Data;
using System.Runtime.InteropServices;
using System.Text;
using System.IO;

namespace FaceCat
{
    /// <summary>
    /// 图表组件
    /// </summary>
    public class MyChart : FCSplitLayoutDiv, FCTouchEventCallBack, FCListenerMessageCallBack, FCInvokeEventCallBack
    {
        public MyChart()
        {
            setBackColor(FCColor.None);
            setBorderColor(FCColor.None);
            setLayoutStyle(FCLayoutStyle.TopToBottom);
            setSize(new FCSize(400, 400));
            MainFrame.m_charts.add(this);
        }

        /// <summary>
        /// 图表
        /// </summary>
        public FCChartEx m_chart;

        public String m_code = "600000.SH";

        public String m_bindCode = "";

        public int m_subscription = 0;

        public int m_cycle = -1;

        public void onSearchCode(String code)
        {
            m_code = code;
            if (m_cycle > 0)
            {
                m_lastPixel = m_chart.m_hScalePixel;
            }
            searchSecurity(code, m_cycle);
        }

        /// <summary>
        /// 客户端Tick数据缓存
        /// </summary>
        private ClientTickDataCache m_clientTickDataCache = new ClientTickDataCache();

        /// <summary>
        /// 历史数据缓存
        /// </summary>
        private ArrayList<SecurityData> m_securityDatasCache = new ArrayList<SecurityData>();

        /// <summary>
        /// 回调方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="message"></param>
        /// <param name="invoke"></param>
        public void callListenerMessageEvent(Object sender, FCMessage message, Object invoke)
        {
            callInvokeEvent(FCEventID.Invoke, sender, message, invoke);
            //m_chart.invoke(message);
        }

        /// <summary>
        /// 请求ID
        /// </summary>
        int m_requestID = -1;

        public int m_lastChangeID;

        public override void onPaint(FCPaint paint, FCRect clipRect)
        {
            if (m_lastChangeID != FCNative.getChangeID())
            {
                m_lastChangeID = FCNative.getChangeID();
                if (MyColor.m_style == 0)
                {
                    chartToBlack(m_chart);
                }
                else
                {
                    chartToWhite(m_chart);
                }
            }
            base.onPaint(paint, clipRect);
        }

        public double m_lastPixel = 11;

        /// <summary>
        /// 绑定历史数据
        /// </summary>
        /// <param name="chart"></param>
        /// <param name="historyDatas"></param>
        public void bindHistoryDatas(String code, int cycle, ArrayList<SecurityData> historyDatas, bool refresh)
        {
            if (code == m_code && m_cycle == cycle)
            {
                m_bindCode = code;
                if (MyColor.m_style == 0)
                {
                    chartToBlack(m_chart);
                }
                else
                {
                    chartToWhite(m_chart);
                }
                if (cycle == 0)
                {
                    m_chart.m_upColor = MyColor.USERCOLOR168;
                    m_chart.m_downColor = MyColor.USERCOLOR169;
                }
                m_chart.m_datas.clear();
                m_chart.m_shapes.clear();
                m_chart.resetChartVisibleRecord();
                m_chart.m_lastValidIndex = -1;
                m_chart.checkChartLastVisibleIndex();
                m_chart.m_candlePaddingTop = 30;
                m_chart.m_candlePaddingBottom = 10;
                if (m_cycle == 0)
                {
                    m_chart.m_cycle = "trend";
                    m_chart.m_hScaleFormat = "HH:mm";
                    m_chart.m_autoFillHScale = true;
                    m_chart.m_magnitude = 100;
                    m_chart.m_rightSpace = 0;
                    m_chart.m_leftVScaleWidth = 60;
                }
                else if (m_cycle < 1440)
                {
                    m_chart.m_cycle = "minute";
                    m_chart.m_hScaleFormat = "HH:mm";
                    m_chart.m_autoFillHScale = false;
                    m_chart.m_magnitude = 10000;
                    m_chart.m_hScalePixel = m_lastPixel;
                    m_lastPixel = m_chart.m_hScalePixel;
                    m_chart.m_rightSpace = 20;
                    m_chart.m_leftVScaleWidth = 0;
                }
                else
                {
                    m_chart.m_cycle = "day";
                    m_chart.m_hScaleFormat = "yyyy-MM-dd";
                    m_chart.m_autoFillHScale = false;
                    m_chart.m_magnitude = 10000;
                    m_chart.m_hScalePixel = m_lastPixel;
                    m_lastPixel = m_chart.m_hScalePixel;
                    m_chart.m_rightSpace = 20;
                    m_chart.m_leftVScaleWidth = 0;
                }
                Security security = new Security();
                if (DataCenter.m_securityService.getSecurityByCode(m_code, ref security))
                {
                    String showCode = security.m_code.Substring(0, security.m_code.IndexOf("."));
                    String sName = showCode + " " + security.m_name;
                    m_chart.m_text = sName;
                }
                m_chart.m_datas.Capacity = historyDatas.size() + 10;
                SecurityData[] ary = historyDatas.ToArray();
                m_chart.m_datas.AddRange(ary);
                if (cycle == 0 && m_chart.m_datas.size() > 0)
                {
                    m_chart.m_firstOpen = m_chart.m_datas.get(m_chart.m_datas.size() - 1).m_close;
                }
                addAvgLine();
                m_chart.resetChartVisibleRecord();
                m_chart.checkChartLastVisibleIndex();
                m_chart.calcChartIndicator();
                if (MainFrame.m_mainFrame.m_latestData != null && MainFrame.m_mainFrame.m_latestData.m_requestID == MainFrame.m_mainFrame.m_requestID1)
                {
                    lock (m_securityDatasCache)
                    {
                        m_securityDatasCache.Clear();
                        m_securityDatasCache.AddRange(historyDatas.ToArray());
                        m_clientTickDataCache.m_code = m_code;
                        m_clientTickDataCache.m_lastAmount = MainFrame.m_mainFrame.m_latestData.m_amount;
                        m_clientTickDataCache.m_lastDate = MainFrame.m_mainFrame.m_latestData.m_date;
                        m_clientTickDataCache.m_lastVolume = MainFrame.m_mainFrame.m_latestData.m_volume;
                    }
                    newData(MainFrame.m_mainFrame.m_latestData, MainFrame.m_mainFrame.m_latestData.m_requestID, false);
                }
                if (refresh)
                {
                    invalidate();
                }
            }
        }

        /// <summary>
        /// 添加均价线
        /// </summary>
        public void addAvgLine()
        {
            if (m_cycle == 0)
            {
                Security security = new Security();
                if (DataCenter.m_securityService.getSecurityByCode(m_code, ref security))
                {
                    int validIndex = -1;
                    m_chart.m_shapes.clear();
                    BaseShape shape = null;
                    if (security.m_type > 0)
                    {
                        shape = new BaseShape();
                        shape.m_color = MyColor.USERCOLOR200;
                        shape.m_shapeName = "avg";
                        m_chart.m_shapes.add(shape);
                    }
                    for (int i = 0; i < m_chart.m_datas.size(); i++)
                    {
                        if (shape != null)
                        {
                            double avgValue = 0;
                            double sumVolume = 0;
                            double sumPrice = 0;
                            for (int j = 0; j <= i; j++)
                            {
                                sumVolume += m_chart.m_datas[j].m_volume;
                                sumPrice += m_chart.m_datas[j].m_amount;
                            }
                            if (sumVolume > 0)
                            {
                                avgValue = sumPrice / sumVolume;
                            }else{
                            avgValue = m_chart.m_datas.get(i).m_close;
                        }
                            shape.m_datas.add(avgValue);
                        }
                        if (m_chart.m_datas[i].m_volume > 0)
                        {
                            validIndex = i;
                        }
                    }
                    m_chart.m_lastValidIndex = validIndex;

                }
            }
        }

        /// <summary>
        /// 添加组件方法
        /// </summary>
        public override void onAdd()
        {
            base.onAdd();
            if (m_chart == null)
            {
                FCSplitLayoutDiv topDiv = new FCSplitLayoutDiv();
                topDiv.setSize(new FCSize(400, 30));
                topDiv.setBackColor(FCColor.None);
                topDiv.setBorderColor(FCColor.None);
                addView(topDiv);
                FCDiv bottomDiv = new FCDiv();
                bottomDiv.setBackColor(FCColor.None);
                bottomDiv.setBorderColor(FCColor.None);
                addView(bottomDiv);
                getSplitter().setBounds(new FCRect(0, 30, getWidth(), 31));
                setFirstView(topDiv);
                setSecondView(bottomDiv);

                m_chart = new FCChartEx();
                m_chart.m_myChart = this;
                bottomDiv.addView(m_chart);
                m_chart.setBorderColor(FCColor.None);
                m_chart.setDock(FCDockStyle.Fill);
                m_chart.m_cycle = "day";
                m_chart.m_allowDragChartDiv = true;
                m_chart.setBorderColor(FCColor.None);
                m_chart.m_crossTipColor = MyColor.USERCOLOR219;
                m_chart.m_leftVScaleWidth = 0;
                m_chart.m_rightVScaleWidth = 60;
                m_chart.m_candlePaddingTop = 30;
                m_chart.m_hScaleHeight = 25;
                m_chart.m_hScaleTextDistance = 8;
                m_chart.m_candlePaddingBottom = 10;
                if (MyColor.m_style == 0)
                {
                    chartToBlack(m_chart);
                }
                else
                {
                    chartToWhite(m_chart);
                }
                m_chart.m_candleDivPercent = 0.7;
                m_chart.m_volDivPercent = 0.3;
                m_chart.m_indDivPercent = 0;
                m_chart.m_candleStyle = "rect2";
                m_chart.m_barStyle = "rect2";

                topDiv.setLayoutStyle(FCLayoutStyle.RightToLeft);
                FCLayoutDiv rLayout = new FCLayoutDiv();
                rLayout.setBorderColor(FCColor.None);
                rLayout.setBackColor(FCColor.None);
                topDiv.addView(rLayout);
                FCLayoutDiv lLayout = new FCLayoutDiv();
                lLayout.setBorderColor(FCColor.None);
                lLayout.setBackColor(FCColor.None);
                lLayout.setAllowPreviewsEvent(true);
                lLayout.setAllowDragScroll(true);
                lLayout.setShowHScrollBar(true);
                topDiv.addView(lLayout);
                lLayout.getHScrollBar().setHeight(0);
                topDiv.getSplitter().setBounds(new FCRect(topDiv.getWidth(), 0, topDiv.getWidth(), topDiv.getHeight()));
                topDiv.getSplitter().setBorderColor(FCColor.None);
                topDiv.setFirstView(rLayout);
                topDiv.setSecondView(lLayout);

                ArrayList<String> cycles = new ArrayList<string>();
                cycles.add("1");
                cycles.add("5");
                cycles.add("10");
                cycles.add("15");
                cycles.add("20");
                cycles.add("30");
                cycles.add("60");
                cycles.add("90");
                cycles.add("120");
                cycles.add("日");
                cycles.add("周");
                cycles.add("月");
                cycles.add("季");
                cycles.add("半");
                cycles.add("年");
                ArrayList<int> cyclesInts = new ArrayList<int>();
                cyclesInts.add(1);
                cyclesInts.add(5);
                cyclesInts.add(10);
                cyclesInts.add(15);
                cyclesInts.add(20);
                cyclesInts.add(30);
                cyclesInts.add(60);
                cyclesInts.add(90);
                cyclesInts.add(120);
                cyclesInts.add(1440);
                cyclesInts.add(10080);
                cyclesInts.add(43200);
                cyclesInts.add(129600);
                cyclesInts.add(259200);
                cyclesInts.add(518400);
                for (int i = 0; i < cycles.size(); i++)
                {
                    CycleButton btnCycle = new CycleButton();
                    btnCycle.setBorderColor(FCColor.None);
                    btnCycle.setSize(new FCSize(27, 30));
                    btnCycle.setText(cycles.get(i));
                    btnCycle.m_cycle = cyclesInts.get(i);
                    btnCycle.m_chart = this;
                    btnCycle.setName(cyclesInts.get(i).ToString());
                    lLayout.addView(btnCycle);
                    btnCycle.addEvent(this, "onclick", this);
                    m_cycleButtons.add(btnCycle);
                }

                m_chart.addEvent(this, "oninvoke", this);
            }
        }

        public ArrayList<CycleButton> m_cycleButtons = new ArrayList<CycleButton>();

        public override void delete()
        {
            if (!isDeleted())
            {
                DataCenter.m_historyServiceClient.removeListener(m_requestID);
            }
            base.delete();
        }

        /// <summary>
        /// 查询代码
        /// </summary>
        /// <param name="code"></param>
        /// <param name="cycle"></param>
        public void searchSecurity(String code, int cycle)
        {
            m_chart.m_floatStrs.clear();
            m_subscription = m_chart.getSubScription();
            m_code = code;
            int oldReqID = m_requestID;
            m_requestID = FCClientService.getRequestID();
            if (oldReqID != -1)
            {
                DataCenter.m_historyServiceClient.removeListener(oldReqID);
                //DataCenter.m_historyServiceClient.stopData(oldReqID);
            }
            DataCenter.m_historyServiceClient.addListener(m_requestID, this, this);
            int realCycle = m_cycle;
            if (realCycle > 0)
            {
                if (realCycle < 1440)
                {
                    realCycle = 1;
                }
                else
                {
                    realCycle = 1440;
                }
            }
            DataCenter.m_historyServiceClient.reqData(m_requestID, m_code, realCycle, 0, 0, 0);
            if (cycle == 0)
            {
                m_chart.m_subComboBox.setVisible(false);
            }
            else
            {
                Security security = new Security();
                if (DataCenter.m_securityService.getSecurityByCode(m_code, ref security))
                {
                    if (security.m_type > 0)
                    {
                        m_chart.m_subComboBox.setVisible(true);
                    }
                    else
                    {
                        m_chart.m_subComboBox.setVisible(false);
                    }
                }
                else
                {
                    m_chart.m_subComboBox.setVisible(false);
                }
            }
        }

        public override void update()
        {
            if (m_cycleButtons.size() > 0)
            {
                int dWidth = getWidth() - m_chart.m_rightVScaleWidth;
                int cWidth = dWidth / m_cycleButtons.size();
                int addWidth = 0;
                if (cWidth < 27)
                {
                    cWidth = 27;
                }
                else if (cWidth > 35)
                {
                    cWidth = 35;
                }
                else
                {
                    addWidth = dWidth - cWidth * m_cycleButtons.size();
                }
                for (int i = 0; i < m_cycleButtons.size(); i++)
                {
                    m_cycleButtons.get(i).setWidth(cWidth);
                }
                if (addWidth > 0)
                {
                    for (int i = m_cycleButtons.size() - 1; i >= 0; i--)
                    {
                        if (addWidth > 0)
                        {
                            m_cycleButtons.get(i).setWidth(m_cycleButtons.get(i).getWidth() + 1);
                            addWidth--;
                        }
                    }
                }
            }
            base.update();
        }

        /// <summary>
        /// 设置属性
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        public override void setAttribute(string name, string value)
        {
            if (name == "cycle")
            {
                m_cycle = FCTran.strToInt(value);
            }
            else if (name == "candledivpercent")
            {
                m_chart.m_candleDivPercent = FCTran.strToDouble(value);
            }
            else if (name == "voldivpercent")
            {
                m_chart.m_volDivPercent = FCTran.strToDouble(value);
            }
            else
            {
                base.setAttribute(name, value);
            }
        }

        /// <summary>
        /// 点击事件
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="sender"></param>
        /// <param name="touchInfo"></param>
        /// <param name="invoke"></param>
        public override void callTouchEvent(string eventName, object sender, FCTouchInfo touchInfo, object invoke)
        {
            base.callTouchEvent(eventName, sender, touchInfo, invoke);
            FCView view = sender as FCView;
            if (view is CycleButton)
            {
                if (m_cycle == 0)
                {
                    m_chart.m_hScalePixel = 11;
                }
                else
                {
                    m_lastPixel = m_chart.m_hScalePixel;
                }
                m_cycle = FCTran.strToInt(view.getName());
                view.getParent().invalidate();
                searchSecurity(m_code, m_cycle);
                m_chart.focus();
            }
        }

        /// <summary>
        /// 图表的黑色风格
        /// </summary>
        /// <param name="chart"></param>
        public void chartToBlack(FCChart chart)
        {
            chart.m_scaleColor = FCColor.rgb(75, 75, 75);
            chart.m_crossLineColor = FCColor.rgb(100, 100, 100);
            chart.m_gridColor = FCColor.rgb(50, 50, 50);
            chart.m_upColor = FCColor.rgb(186, 56, 18);
            chart.m_downColor = FCColor.rgb(31, 182, 177);
            if (m_cycle == 0)
            {
                chart.m_downColor = FCColor.rgb(15, 193, 118);
            }
		chart.m_trendColor = FCColor.rgb(255, 255, 255);
            ArrayList<long> indicatorColors = new ArrayList<long>();
            chart.m_indicatorColors = indicatorColors;
            indicatorColors.add(FCColor.rgb(255, 255, 255));
            indicatorColors.add(FCColor.rgb(255, 255, 0));
            indicatorColors.add(FCColor.rgb(255, 0, 255));
            indicatorColors.add(FCColor.rgb(255, 0, 0));
            indicatorColors.add(FCColor.rgb(0, 255, 255));
            indicatorColors.add(FCColor.rgb(0, 255, 0));
            indicatorColors.add(FCColor.rgb(255, 255, 0));
            indicatorColors.add(FCColor.rgb(255, 255, 255));
            chart.m_candleStyle = "rect2";
        }

        /// <summary>
        /// 白色风格
        /// </summary>
        /// <param name="chart"></param>
        public void chartToWhite(FCChart chart)
        {
            chart.m_scaleColor = FCColor.rgb(150, 150, 150);
            chart.m_crossLineColor = FCColor.rgb(150, 150, 150);
            chart.m_gridColor = FCColor.rgba(150, 150, 150, 125);
            chart.m_upColor = FCColor.rgb(255, 80, 80);
            chart.m_downColor = MyColor.USERCOLOR169;
            if (m_cycle == 0)
            {
                chart.m_downColor = FCColor.rgb(15, 193, 118);
            }
chart.m_trendColor = FCColor.rgb(0, 0, 0);
            ArrayList<long> indicatorColors = new ArrayList<long>();
            chart.m_indicatorColors = indicatorColors;
            indicatorColors.add(FCColor.rgb(50, 50, 50));
            indicatorColors.add(FCColor.rgb(50, 50, 50));
            indicatorColors.add(FCColor.rgb(50, 50, 50));
            indicatorColors.add(FCColor.rgb(50, 50, 50));
            indicatorColors.add(FCColor.rgb(50, 50, 50));
            indicatorColors.add(FCColor.rgb(50, 50, 50));
            indicatorColors.add(FCColor.rgb(100, 100, 100));
            indicatorColors.add(FCColor.rgb(50, 50, 50));
            chart.m_candleStyle = "rect";
        }

        /// <summary>
        /// 插入数据
        /// </summary>
        /// <param name="chart">证券视图</param>
        /// <param name="dataSource">数据源</param>
        /// <param name="fields">字段</param>
        /// <param name="securityData">证券数据</param>
        /// <returns>索引</returns>
        public static int insertData(FCChartEx chart, SecurityData securityData)
        {
            if (chart.m_datas.size() > 0)
                {
                    double date = securityData.m_date;
                    double lastDate = chart.m_datas[chart.m_datas.size() - 1].m_date;
                    if (date == lastDate)
                    {
                        chart.m_datas[chart.m_datas.size() - 1] = securityData;
                    }
                    else
                    {
                        chart.m_datas.add(securityData);
                    }
                }
                else
                {
                    chart.m_datas.add(securityData);
                }
            return 1;
        }

        public int m_clearRequestID = -1;

        /// <summary>
        /// 接收最新数据
        /// </summary>
        /// <param name="latestData"></param>
        public void newData(SecurityLatestData latestData, int requestID, bool refresh)
        {
            if (latestData.m_code != m_bindCode)
            {
                return;
            }
            lock (m_securityDatasCache)
            {
                if (m_cycle == 0)
                {
                    m_chart.m_firstOpen = latestData.m_lastClose;
                }
                //集合竞价处理
                if (m_cycle == 0 && latestData.m_volume == 0)
                {
                    m_clearRequestID = requestID;
                    for (int i = 0; i < m_chart.m_datas.size(); i++)
                    {
                        SecurityData sData = m_chart.m_datas.get(i);
                        sData.m_open = 0;
                        sData.m_close = 0;
                        sData.m_high = 0;
                        sData.m_low = 0;
                        sData.m_volume = 0;
                        sData.m_amount = 0;
                    }
                    m_chart.m_shapes.clear();
                    m_chart.calculateChartMaxMin();
                    m_chart.checkChartLastVisibleIndex();
                    if (refresh)
                    {
                        m_chart.invalidate();
                    }
                }
                else if (m_clearRequestID == requestID)
                {
                    searchSecurity(latestData.m_code, 0);
                    m_clearRequestID = -1;
                }
                else
                {
                    SecurityData newData = new SecurityData();
                    newData.m_amount = latestData.m_amount;
                    newData.m_volume = latestData.m_volume;
                    newData.m_high = latestData.m_high;
                    newData.m_low = latestData.m_low;
                    newData.m_close = latestData.m_close;
                    newData.m_open = latestData.m_open;
                    newData.m_date = latestData.m_date;
                    if (m_securityDatasCache.Count > 0)
                    {
                        //后复权
                        if (m_subscription == 2)
                        {
                            if (StockService.m_factors.containsKey(latestData.m_code))
                            {
                                ArrayList<ADJUSTMENTFACTOR> factor = StockService.m_factors.get(latestData.m_code);
                                SecurityData sData = new SecurityData();
                                sData.m_date = (int)(latestData.m_date / 86400) * 86400;
                                sData.m_close = latestData.m_close;
                                sData.m_high = latestData.m_high;
                                sData.m_low = latestData.m_low;
                                sData.m_open = latestData.m_open;
                                StockService.ConvertXDRAfterPrice(latestData.m_code, sData, sData.m_date, factor);
                                newData.m_close = sData.m_close;
                                newData.m_high = sData.m_high;
                                newData.m_low = sData.m_low;
                                newData.m_open = sData.m_open;
                            }
                        }
                    }
                    bool lastRecordIsVisible = false;
                    if (m_chart.m_lastVisibleIndex == m_chart.m_datas.size() - 1)
                    {
                        lastRecordIsVisible = true;
                    }
                    m_clientTickDataCache.m_code = latestData.m_code;
                    int oldDatasSize = m_securityDatasCache.Count;
                    StockService.mergeLatestData(latestData.m_code, m_securityDatasCache, newData, m_clientTickDataCache, m_cycle);
                    if (m_securityDatasCache.size() > 0)
                    {
                        int startIndex = oldDatasSize - 1;
                        if (startIndex < 0)
                        {
                            startIndex = 0;
                        }
                        if (m_cycle == 0)
                        {
                            startIndex = 0;
                        }
                        for (int i = startIndex; i < m_securityDatasCache.Count; i++)
                        {
                            SecurityData securityData = m_securityDatasCache[i];
                            if (securityData.m_open > 0 && securityData.m_volume > 0 && securityData.m_amount > 0)
                            {
                                if (m_cycle == 0)
                                {
                                    if (i < m_chart.m_datas.size())
                                    {
                                        if (m_chart.m_datas[i].m_date == securityData.m_date)
                                        {
                                            m_chart.m_datas[i] = securityData;
                                        }
                                    }
                                }
                                else
                                {
                                    insertData(m_chart, securityData);
                                }
                            }
                        }
                        m_chart.m_shapes.clear();
                        addAvgLine();
                        m_chart.calculateChartMaxMin();
                        m_chart.checkChartLastVisibleIndex();
                        if (lastRecordIsVisible && m_chart.m_lastVisibleIndex != m_chart.m_datas.size() - 1)
                        {
                            m_chart.m_lastRecordIsVisible = true;
                            m_chart.m_lastVisibleIndex = m_chart.m_datas.size() - 1;
                            int workingAreaWidth = m_chart.getChartWorkAreaWidth();
                            int maxVisibleRecord = m_chart.getChartMaxVisibleCount(m_chart.m_hScalePixel, workingAreaWidth);
                            m_chart.m_firstVisibleIndex = m_chart.m_lastVisibleIndex - maxVisibleRecord + 1;
                            if (m_chart.m_firstVisibleIndex < 0)
                            {
                                m_chart.m_firstVisibleIndex = 0;
                            }
                        }
                        if (refresh)
                        {
                            m_chart.invalidate();
                        }
                    }
                }
            }
        }

        public void callInvokeEvent(string eventName, object sender, object args, object invoke)
        {
            if (args != null)
            {
                FCMessage message = args as FCMessage;
                if (message != null)
                {
                    if (message.m_serviceID == HistoryServiceClient.SERVICEID)
                    {
                        if (message.m_functionID == HistoryServiceClient.FUNCTIONID_GETDATA)
                        {
                            if (message.m_requestID == m_requestID)
                            {
                                String code = "";
                                int cycle = 0;
                                int subscription = 0;
                                double startDate = 0, endDate = 0, nowDate = 0, nowVolume = 0, nowAmount = 0;
                                ArrayList<SecurityData> securityDatas = HistoryServiceClient.getDatas(ref code, ref cycle, ref startDate, ref endDate, ref subscription, ref nowDate, ref nowVolume, ref nowAmount, message.m_body, message.m_bodyLength);
                                if (m_cycle > 0)
                                {
                                    if (m_subscription == 1)
                                    {
                                        StockService.ConvertXDR(code, 1, securityDatas);
                                    }
                                    else if (m_subscription == 2)
                                    {
                                        StockService.ConvertXDR(code, 2, securityDatas);
                                    }
                                    if (m_cycle < 1440)
                                    {
                                        if (m_cycle > 1)
                                        {
                                            ArrayList<SecurityData> newDatas = new ArrayList<SecurityData>();
                                            StockService.multiMinuteSecurityDatas(newDatas, securityDatas, m_cycle);
                                            securityDatas = newDatas;
                                        }
                                    }
                                    else
                                    {
                                        if (m_cycle == 10080)
                                        {
                                            ArrayList<SecurityData> newDatas = new ArrayList<SecurityData>();
                                            StockService.getHistoryWeekDatas(newDatas, securityDatas);
                                            securityDatas = newDatas;
                                        }
                                        else if (m_cycle == 43200)
                                        {
                                            ArrayList<SecurityData> newDatas = new ArrayList<SecurityData>();
                                            StockService.getHistoryMonthDatas(newDatas, securityDatas);
                                            securityDatas = newDatas;
                                        }
                                        else if (m_cycle == 129600)
                                        {
                                            ArrayList<SecurityData> newDatas = new ArrayList<SecurityData>();
                                            StockService.getHistorySeasonDatas(newDatas, securityDatas);
                                            securityDatas = newDatas;
                                        }
                                        else if (m_cycle == 259200)
                                        {
                                            ArrayList<SecurityData> newDatas = new ArrayList<SecurityData>();
                                            StockService.getHistoryHalfYearDatas(newDatas, securityDatas);
                                            securityDatas = newDatas;
                                        }
                                        else if (m_cycle == 518400)
                                        {
                                            ArrayList<SecurityData> newDatas = new ArrayList<SecurityData>();
                                            StockService.getHistoryYearDatas(newDatas, securityDatas);
                                            securityDatas = newDatas;
                                        }
                                    }
                                }
                                bindHistoryDatas(code, m_cycle, securityDatas, true);
                            }
                        }
                    }
                }
            }
        }

        public void clearDatas()
        {
            m_securityDatasCache.Clear();
            m_chart.m_datas.clear();
            m_chart.m_shapes.clear();
            m_chart.invalidate();
        }
    }

    /// <summary>
    /// 周期按钮
    /// </summary>
    public class CycleButton : FCButton
    {
        public CycleButton()
        {
            setFont(new FCFont("Default", 14));
        }

        public int m_cycle;

        public MyChart m_chart;

        public override long getPaintingTextColor()
        {
            if (MyColor.m_style == 0)
            {
                return FCColor.rgb(200, 200, 200);
            }
            return base.getPaintingTextColor();
        }

        public override void onPaintForeground(FCPaint paint, FCRect clipRect)
        {
            int width = getWidth(), height = getHeight();
            int cWidth = clipRect.right - clipRect.left;
            paint.drawLine(FCColor.Border, 1, 0, width - 1, 5, width - 1, height - 5);
            if (m_chart != null && m_chart.m_cycle != 0 && m_chart.m_cycle == m_cycle)
            {
                paint.fillRect(FCColor.Pushed, 1, 1, width - 1, height - 1);
                paint.drawRect(MyColor.USERCOLOR109, 1, 0, 1, 1, width - 1, height - 1);
            }
            base.onPaintForeground(paint, clipRect);
        }
    }
}
